/**
 * @file 快捷键安装器（主进程）
 * 通过为每个窗口动态构建只包含“快捷键项”的 Menu，实现基于 accelerator 的快捷键处理。
 * 关键点：
 * - 默认值 + 用户 overrides（仅存差异）合并为“有效快捷键”，随 overrides 改变自动重建菜单
 * - 每个窗口独立菜单，避免 before-input-event 抢占 DOM
 * - ESC 特殊路由：根据 layout/content/聚焦 tab 的 escPriority 选择目标并通过 IPC 转发
 */

import type { Tab } from '#/browser/entities/tab.entity'
import { TabManager } from '#/browser/managers/tab.manager'
import { separateCommand, windowCommand } from '#/shortcuts'
import { BaseWindow, Menu, MenuItem, webContents } from 'electron'
import { getEffectiveShortcuts } from '~shared/utils/shortcuts'
import { LANGUAGE_CONFIG, type SupportedLanguage } from '~shared/constants'
import { createStorageState, systemState } from 'global-state'
import { ShortcutsConfig } from '~types/global-state'

export const shortcutsState = createStorageState(
  'shortcuts',
  {
    overrides: {}
  } as ShortcutsConfig,
  2
)

function getCurrentLanguage(): SupportedLanguage {
  const lang = systemState.state.language as string | undefined
  const supported = LANGUAGE_CONFIG.SUPPORTED_LANGUAGES as readonly string[]
  return supported.includes(lang ?? '')
    ? (lang as SupportedLanguage)
    : (LANGUAGE_CONFIG.DEFAULT_LANGUAGE as SupportedLanguage)
}

/**
 * 将“快捷键监听”从 before-input-event 改为使用 Menu/MenuItem 的 accelerator
 * - 优点：可与 DOM 事件更加自然地并存（不再抢在 DOM 之前处理）
 * - 设计：为每个窗口动态构建只包含“快捷键项”的菜单，并挂到该窗口上
 */
/**
 * 在普通窗口安装快捷键菜单（窗口内命令）
 * - 使用 getEffectiveShortcuts(process.platform, shortcutsState.state.overrides)
 *   以“默认值 + 用户覆盖”得到有效快捷键
 * - 仅为 windowCommand 注册对应命令的加速器
 * - 监听 overrides 变更，重建当前窗口菜单
 *
 * @param deps.layoutTab Layout 容器 tab
 * @param deps.win       目标窗口（将把菜单挂载到该窗口）
 * @param deps.tabManager Tab 管理器（用于定位 activeTab、命令上下文）
 * @returns 回收函数：停止监听 + 还原窗口菜单
 */

export function installWindowShortcuts(deps: {
  layoutTab: Tab
  win: BaseWindow
  tabManager: TabManager
}): () => void {
  const { layoutTab, tabManager, win } = deps
  const layoutWebContents = layoutTab.view.webContents

  const windowCommandRegistry = windowCommand
  const prevMenu = Menu.getApplicationMenu() || null
  const buildMenu = () => {
    const menu = new Menu()

    // ESC 专用
    menu.append(
      new MenuItem({
        label: 'Esc',
        accelerator: 'Esc',
        click: () => {
          try {
            const focused = webContents.getFocusedWebContents()
            const layoutId = layoutWebContents.id
            const isLayoutFocused = focused?.id === layoutId
            const activeId = tabManager.activeTab?.tab.webContentsId
            const candidateB = isLayoutFocused
              ? activeId
                ? webContents.fromId(activeId)
                : null
              : focused || null
            const prioLayout = Number(layoutTab.data.escPriority || 0)
            const prioB = candidateB
              ? Number(global.tabMap.get(candidateB.id)?.data.escPriority || 0)
              : 0
            if (Math.max(prioLayout, prioB) <= 0) return
            const target = prioLayout >= prioB ? layoutWebContents : candidateB
            const sourceId = candidateB?.id
            target?.send('esc:press', sourceId)
          } catch (error) {
            console.warn('[shortcuts] 发送 ESC 事件失败:', error)
          }
        }
      })
    )

    // 动态快捷键项（从全局配置读取，仅注册本窗口支持的命令）
    const lang = getCurrentLanguage()
    const list = getEffectiveShortcuts(shortcutsState.state.overrides, lang)
    const submenu = new Menu()
    for (const s of list) {
      if (!s?.id || !s?.key || s.enabled === false) continue
      if (!windowCommandRegistry.has(s.id)) continue
      submenu.append(
        new MenuItem({
          label: s.name || s.id,
          accelerator: s.key,
          click: (_item, _bw) => {
            try {
              const focused = webContents.getFocusedWebContents()
              const focusedId = focused?.id
              const layoutId = layoutWebContents.id
              const isFromLayout = focusedId === layoutId
              const focusedTab = focusedId ? global.tabMap.get(focusedId) : undefined
              // 计算 sourceTab：layout 焦点 -> activeTab；否则取聚焦 tab
              const sourceTab = isFromLayout
                ? tabManager.activeTab?.tab || layoutTab
                : focusedTab || tabManager.activeTab?.tab || layoutTab

              const handler = windowCommandRegistry.get(s.id)
              if (!handler) return
              handler({ tabManager, layoutTab, sourceTab })
            } catch (error) {
              console.warn('[shortcuts] 命令执行失败:', error)
            }
          }
        })
      )
    }

    if (submenu.items.length > 0) {
      const topLabel = getCurrentLanguage() === 'zhHans' ? '快捷键' : 'Shortcuts'
      menu.append(new MenuItem({ label: topLabel, submenu }))
    }

    win.setMenu(menu)
  }
  const stopWatchLang = systemState.watch('language', () => buildMenu())

  buildMenu()
  const stopWatch = shortcutsState.watch('overrides', () => buildMenu())

  return () => {
    try {
      stopWatch?.()
      stopWatchLang?.()
    } catch {
      void 0
    }
    try {
      win.setMenu(prevMenu)
    } catch {
      void 0
    }
  }
}

/**
 * 独立窗口（Separate）使用 Menu 加速器
 */
/**
 * 在独立窗口（Separate）安装快捷键菜单（跨 tab 的独立窗口用）
 * - 仅为 separateCommand 注册命令加速器
 * - 与普通窗口类似：随 overrides 改变自动重建菜单
 * - ESC 路由策略：layout 焦点优先转发给 contentTab，否则按聚焦来源与 escPriority 决定
 *
 * @param deps.layoutTab  Layout 容器 tab
 * @param deps.contentTab 内容 tab
 * @param deps.win        目标窗口
 * @returns 回收函数：停止监听 + 还原窗口菜单
 */

export function installSeparateShortcuts(deps: {
  layoutTab: Tab
  contentTab: Tab
  win: BaseWindow
}): () => void {
  const { layoutTab, contentTab, win } = deps
  const layoutWebContents = layoutTab.view.webContents

  const separateCommandRegistry = separateCommand
  const prevMenu = Menu.getApplicationMenu() || null

  const buildMenu = () => {
    const menu = new Menu()

    // ESC 专用：layout 焦点 -> 转发 contentTab；否则按聚焦来源
    menu.append(
      new MenuItem({
        label: 'Esc',
        accelerator: 'Esc',
        click: () => {
          try {
            const focused = webContents.getFocusedWebContents()
            const layoutId = layoutWebContents.id
            const isLayoutFocused = focused?.id === layoutId
            const candidateB = isLayoutFocused ? contentTab.view.webContents : focused || null
            const prioLayout = Number(layoutTab.data.escPriority || 0)
            const prioB = candidateB
              ? Number(global.tabMap.get(candidateB.id)?.data.escPriority || 0)
              : 0
            if (Math.max(prioLayout, prioB) <= 0) return
            const target = prioLayout >= prioB ? layoutWebContents : candidateB
            const sourceId = candidateB?.id
            target?.send('esc:press', sourceId)
          } catch (error) {
            console.warn('[shortcuts] 发送 ESC 事件失败:', error)
          }
        }
      })
    )

    // 动态快捷键项
    const lang = getCurrentLanguage()
    const list = getEffectiveShortcuts(shortcutsState.state.overrides, lang)
    const submenu = new Menu()
    for (const s of list) {
      if (!s?.id || !s?.key || s.enabled === false) continue
      if (!separateCommandRegistry.has(s.id)) continue
      submenu.append(
        new MenuItem({
          label: s.name || s.id,
          accelerator: s.key,
          click: (_item, _bw) => {
            try {
              const handler = separateCommandRegistry.get(s.id)
              if (!handler) return
              handler({ layoutTab, contentTab })
            } catch (error) {
              console.warn('[shortcuts] 命令执行失败:', error)
            }
          }
        })
      )
    }

    if (submenu.items.length > 0) {
      const topLabel = getCurrentLanguage() === 'zhHans' ? '快捷键' : 'Shortcuts'
      menu.append(new MenuItem({ label: topLabel, submenu }))
    }

    win.setMenu(menu)
  }

  buildMenu()
  const stopWatch = shortcutsState.watch('overrides', () => buildMenu())

  const stopWatchLang = systemState.watch('language', () => buildMenu())

  return () => {
    try {
      stopWatch?.()
      stopWatchLang?.()
    } catch {
      void 0
    }
    try {
      win.setMenu(prevMenu)
    } catch {
      void 0
    }
  }
}
